package org.open.otalk.api.r1;

import java.util.ArrayList;
import java.util.Collection;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;

import org.jivesoftware.smack.Roster;
import org.jivesoftware.smack.RosterEntry;
import org.jivesoftware.smack.RosterGroup;
import org.jivesoftware.smack.XMPPException;
import org.jivesoftware.smack.packet.Presence;
import org.jivesoftware.smack.util.StringUtils;
import org.open.otalk.R;
import org.open.otalk.aidl.packet.OContact;
import org.open.otalk.aidl.packet.OPresence;
import org.open.otalk.api.util.Status;

import android.content.Context;
import android.os.RemoteException;
import android.util.Log;

public class OTalkRoster {
	private static final String TAG = "OTalkRoster";
	// -------------------------------------------------------

	private final Roster mRoster;
	private OTalkClient mClient;

	private final Map<Integer, String> mDefaultStatusMessages;

	public OTalkRoster(OTalkClient _client) {
		this.mClient = _client;
		mDefaultStatusMessages = createDefaultStatusMessagesMap(mClient.getContext());
		mRoster = mClient.getTalkConnection().getRoster();
	}

	public void addRosterListener() {

	}

	public OContact addContact(String user, String name, String[] groups) {
		RosterEntry contact = mRoster.getEntry(user);
		try {
			mRoster.createEntry(user, name, groups);
			contact = mRoster.getEntry(user);
		} catch (XMPPException e) {
			Log.e(TAG, "Error while adding new contact", e);
			return null;
		}
		return getContactFromRosterEntry(contact);
	}

	/**
	 * {@inheritDoc}
	 */
	public void deleteContact(OContact contact) throws RemoteException {
		try {
			RosterEntry entry = mRoster.getEntry(contact.getJID());
			mRoster.removeEntry(entry);
		} catch (XMPPException e) {
			e.printStackTrace();
		}
	}

	/**
	 * {@inheritDoc}
	 */
	public void createGroup(String groupname) throws RemoteException {
		if (mRoster.getGroup(groupname) == null)
			mRoster.createGroup(groupname);
	}

	/**
	 * {@inheritDoc}
	 */
	public OContact getContact(String jid) throws RemoteException {
		if (mRoster.contains(jid))
			return getContactFromRosterEntry(mRoster.getEntry(jid));
		return null;
	}

	/**
	 * {@inheritDoc}
	 */
	public List<OContact> getContactList() throws RemoteException {
		boolean add = true;
		Collection<RosterEntry> list = mRoster.getEntries();
		List<OContact> coList = new ArrayList<OContact>(list.size());
		for (RosterEntry entry : list) {
			coList.add(getContactFromRosterEntry(entry));
		}
		return coList;
	}

	/**
	 * {@inheritDoc}
	 */
	public List<String> getGroupsNames() throws RemoteException {
		Collection<RosterGroup> groups = mRoster.getGroups();
		List<String> result = new ArrayList<String>(groups.size());
		for (RosterGroup rosterGroup : groups) {
			result.add(rosterGroup.getName());
		}
		return result;
	}

	/**
	 * {@inheritDoc}
	 */
	public void removeRosterListener() throws RemoteException {
		// if (listen != null)
		// mRemoteRosListeners.unregister(listen);
	}

	/**
	 * {@inheritDoc}
	 */
	public void setContactName(String jid, String name) throws RemoteException {
		mRoster.getEntry(jid).setName(name);
	}

	public OPresence getPresence(String jid) throws RemoteException {
		return new OPresence(mRoster.getPresence(jid));
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.beem.project.beem.service.aidl.IRoster#addContactToGroup(java.lang
	 * .String, java.lang.String)
	 */
	public void addContactToGroup(String groupName, String jid)
			throws RemoteException {
		createGroup(groupName);
		RosterGroup group = mRoster.getGroup(groupName);
		try {
			group.addEntry(mRoster.getEntry(jid));
		} catch (XMPPException e) {
			e.printStackTrace();
		}
	}

	/*
	 * (non-Javadoc)
	 * 
	 * @see
	 * com.beem.project.beem.service.aidl.IRoster#removeContactFromGroup(java
	 * .lang.String, java.lang.String)
	 */
	public void removeContactFromGroup(String groupName, String jid)
			throws RemoteException {
		RosterGroup group = mRoster.getGroup(groupName);
		try {
			group.removeEntry(mRoster.getEntry(jid));
		} catch (XMPPException e) {
			e.printStackTrace();
		}
	}

	/**
	 * Get a contact from a RosterEntry.
	 * 
	 * @param entry
	 *            a roster entry containing information for the contact.
	 * @return a contact for this entry.
	 */
	private OContact getContactFromRosterEntry(RosterEntry entry) {
		String user = entry.getUser();
		OContact c = new OContact(user);
		Presence p = mRoster.getPresence(user);

		if (p.getStatus() == null || "".equals(p.getStatus()))
			p.setStatus(mDefaultStatusMessages.get(Status
					.getStatusFromPresence(p)));
		c.setStatus(p);
		try {
			c.setGroups(entry.getGroups());
		} catch (NullPointerException e) {
			Log.d(TAG, "Group list not ready", e);
		}
		Iterator<Presence> iPres = mRoster.getPresences(user);
		while (iPres.hasNext()) {
			p = iPres.next();
			if (!p.getType().equals(Presence.Type.unavailable))
				c.addRes(StringUtils.parseResource(p.getFrom()));
		}
		c.setName(entry.getName());
		// c.setAvatarId(mAvatarIdmap.get(user));
		return c;
	}

	private Map<Integer, String> createDefaultStatusMessagesMap(Context context) {
		Map<Integer, String> defaultStatusMessages = new HashMap<Integer, String>();
		defaultStatusMessages.put(Status.CONTACT_STATUS_AVAILABLE,
				context.getString(R.string.contact_status_msg_available));
		defaultStatusMessages.put(Status.CONTACT_STATUS_AVAILABLE_FOR_CHAT,
				context.getString(R.string.contact_status_msg_available_chat));
		defaultStatusMessages.put(Status.CONTACT_STATUS_AWAY,
				context.getString(R.string.contact_status_msg_away));
		defaultStatusMessages.put(Status.CONTACT_STATUS_BUSY,
				context.getString(R.string.contact_status_msg_dnd));
		defaultStatusMessages.put(Status.CONTACT_STATUS_DISCONNECT,
				context.getString(R.string.contact_status_msg_offline));
		defaultStatusMessages.put(Status.CONTACT_STATUS_UNAVAILABLE,
				context.getString(R.string.contact_status_msg_xa));

		return defaultStatusMessages;
	}

}
